// 放大镜构造函数
class createGlassObj{
    // 构造器中 定义属性属性值
    constructor( element , array ){
        // 定义属性 存储 形参
        this.ele = element ;
        this.arr = array ;

        // 定义属性 存储 多个函数都要使用的数据
        this.show;
        this.img;
        this.mask;
        this.list;
        this.glass;
        this.ulLiImgs;
    }

    // 构造器外 定义函数方法

    // 设定入口函数 
    // 必须命名为 init
    init(){
        // 调用所有需要执行的函数程序
        this.setPage();
        this.setMouse();
        this.setTab();
        this.setMove();
    }


    // 动态 生成页面 
    setPage(){
        // 节点操作

        // // 创建 显示区div标签
        // const oShow = document.createElement('div');
        // // 设定 显示区div标签 class属性
        // oShow.className = 'show' ;

        // // 给 显示区div标签 class属性 新增 show
        // // oShow.classList.add('show');

        // // 创建 显示区中 img标签
        // const oImg = document.createElement('img');
        // // img标签 默认显示 数组中 第一个单元的图片
        // oImg.src = `./images/${this.arr[0].large}` ;

        // // 创建 遮盖层 div标签
        // const oMask = document.createElement('div');
        // // 设定 遮盖层 div标签 class
        // oMask.className = 'mask' ;

        // // 将 img图片标签 遮盖层div标签 写入 显示区标签
        // oShow.appendChild( oImg );
        // oShow.appendChild( oMask );

        // // 列表区 ul标签对象
        // const oUl = document.createElement('ul');
        // // 设定 列表区 ul标签 class
        // oUl.className = 'list' ;

        // // 动态生成 ul>li 标签
        // let ulLiStr = '' ;
        // this.arr.forEach( ( item , index ) => {
        //     // item  是 数组中数据单元存储的 对象
        //     // index 是 数组中数据单元的索引下标
            
        //     // 如果是 第一个 标签 给 ul>li>img 标签 添加 class,active
        //     ulLiStr += index === 0 ? `<li><img class="active" src="./images/${item.small}"></li>` : `<li><img src="./images/${item.small}"></li>`

        // })

        // // 将 字符串 写入 ul标签
        // oUl.innerHTML = ulLiStr ;


        // // 创建 放大区 div标签对象
        // const oGlass = document.createElement('div');
        // // 设定 放大区 div标签 class
        // oGlass.className = 'glass' ;
        // // 设定 放大区 背景图片 
        // // 默认显示数组中第一个对象中存储的图片
        // oGlass.style.backgroundImage = `url('./images/${this.arr[0].large}')` ;

        // // 将 显示区 列表区 放大区 写入 放大镜div标签中
        // this.ele.appendChild( oShow );
        // this.ele.appendChild( oUl );
        // this.ele.appendChild( oGlass );





        // 字符串生成

        // 定义变量 存储 字符串内容
        let str = '' ;

        // 拼接写入 第一个部分固定内容
        // 设定 img标签 图片路径 是 数组中第一个对象存储的数据
        str += `
            <div class="show">
                <img src="./images/${this.arr[0].large}" alt="">
                <div class="mask"></div>
            </div>
            <ul class="list">
        
        `;


        // 根据数组 动态拼接写入 li标签
        this.arr.forEach( (item , index) => {
            // 拼接写入 li标签内容
            // img标签图片 定义 name属性 作为 事件委托的判断依据
            // img标签图片 定义 num属性 存储 索引下标
            str += index === 0 ? `<li><img name="ulLiImg" num="${index}" class="active" src="./images/${item.small}"></li>` : `<li><img name="ulLiImg"  num="${index}" src="./images/${item.small}"></li>`;

        })


        // 拼接写入 第二个固定内容
        // 给 放大区div标签 设定 背景图片 是 数组中第一个单元的图片路径
        str += `
            </ul>
            <div class="glass" style="background-image:url('./images/${this.arr[0].large}')"></div>
        `;


        // 将 动态生成的字符串 写入 放大镜 标签对象中
        this.ele.innerHTML = str ;

        // 获取标签对象 存储到 属性中

        // 显示区div标签
        this.show = this.ele.querySelector('.show');
        // 显示区中img图片标签
        this.img = this.show.querySelector('img');
        // 显示区中mask遮盖层标签
        this.mask = this.show.querySelector('.mask');
        // 列表区ul标签
        this.list = this.ele.querySelector('.list');
        // 放大区div标签
        this.glass = this.ele.querySelector('.glass');
        // 列表区li标签中img标签 因为鼠标最终移入的是img标签
        this.ulLiImgs = this.list.querySelectorAll('li>img');

    }   


    // 鼠标 移入移出
    setMouse(){
        // 给 显示区 添加 鼠标 移入事件
        this.show.addEventListener( 'mouseenter' , ()=>{
            // 遮盖层 放大区 显示
            this.mask.style.display = 'block';
            this.glass.style.display = 'block';
        })


        // 给 显示区 添加 鼠标 移出事件
        this.show.addEventListener( 'mouseleave' , ()=>{
            // 遮盖层 放大区 消失
            this.mask.style.display = 'none';
            this.glass.style.display = 'none';
        })
    }



    // 选项卡效果
    setTab(){
        // 给 父级标签 添加事件 
        this.ele.addEventListener( 'mouseover' , event => {
            // 如果触发的标签 是 ul>li>img 标签 执行程序
            if( event.target.getAttribute('name') === 'ulLiImg' ){
                // 清除 所有 图片标签 class,active 
                // 循环遍历 所有的img标签对象
                this.ulLiImgs.forEach( item => {
                    // item 是 数组中数据单元存储的数据数值 也就是 img图片标签
                    // 清除 class,active样式 
                    item.classList.remove('active');
                })

                // 给 触发事件的img标签 也就是 event.target 添加 class,active
                event.target.classList.add('active');

                // 根据 触发事件的img标签 num属性存储的索引下标
                // 图片标签中 num属性存储的是 img标签的索引下标
                // 也就是 这个 img图片 在 数组中 存储的对象的索引下标
                // 也就是 鼠标经过那个 img图片 
                // 就获取这个图片 在 数组中对象的索引下标 
                // 根据 这个 索引下标 获取 数组中对应的对象 
                // 再从对象中 获取 图片的路径

                // 设定显示区 img标签 src属性
                this.img.src = `./images/${this.arr[ Number( event.target.getAttribute('num') ) ].large}`;

                // 设定放大区 css样式 背景图片路径
                this.glass.style.backgroundImage = `url('./images/${this.arr[ Number( event.target.getAttribute('num') ) ].large}')`;


            }
        })
    }


    // 拖拽效果
    // 基本思路方法 和 之前的鼠标拖拽效果是相同的
    setMove(){
        // 给 show标签 添加 鼠标移动事件
        this.show.addEventListener( 'mousemove' , event => {
            // 获取 外边距
            let oBoxLeft = this.ele.offsetLeft ;
            let oBoxTop = this.ele.offsetTop ;

            // 获取 边框线宽度
            let oShowBorderLeft = this.show.clientLeft ;
            let oShowBorderTop = this.show.clientTop ;

            // 获取 show标签 占位 内容+padding
            let oShowWidth = this.show.clientWidth ;
            let oShowHeight = this.show.clientHeight ;

            // 获取 mask遮盖层 占位 内容+padding+border
            let oMaskWidth = this.mask.offsetWidth ;
            let oMaskHeight = this.mask.offsetHeight ;

            // 计算 遮盖层定位数值
            // 鼠标坐标 - 外边距 - 边框线宽度 - 遮盖层占位/2 
            let x = event.pageX - oBoxLeft - oShowBorderLeft - oMaskWidth / 2 ;
            let y = event.pageY - oBoxTop - oShowBorderTop - oMaskHeight / 2 ;

            // 设定极值 
            
            // 最小值 0 
            x = x < 0 ? 0 : x ;
            y = y < 0 ? 0 : y ;

            // 最大值 显示区占位 - 遮盖层占位
            x = x > oShowWidth - oMaskWidth ? oShowWidth - oMaskWidth : x ;
            y = y > oShowHeight - oMaskHeight ? oShowHeight - oMaskHeight : y ;

            // 将定位数值 赋值给 遮盖层css样式
            this.mask.style.left = x + 'px' ;
            this.mask.style.top = y + 'px' ;

            // 背景图定位 和 遮盖层定位 
            // 方向相反 数值成等比例关系
            // 也就是 遮盖层是向 左 下 定位移动
            // 背景图 是向 右 上 定位移动
            // 比例关系 计算之后是 1:4 的关系 
            this.glass.style.backgroundPosition = `${-x*4}px ${-y*4}px` ;

        })
    }
}